package services.api;

import com.avaje.ebean.Ebean;
import dto.api.*;
import models.application.*;
import models.user.*;
import services.application.AniAppService;
import services.exception.AniDataException;
import utils.MVCUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * User: yeh
 * Date: 2/26/13
 * Time: 6:17 PM
 * For:  wilddragon
 */
public class AniApiEditService extends AniApiService {
    public static void updateApiInfo(Map<String, String> apiUpdateInfoArgs, AniUser curUser){
        //update api info
        MVCUtils.verifyRequiredElements(apiUpdateInfoArgs, ApiInputInfoDto.requiredUpdateFieldKeys);
        ApiInputInfoDto oneApiInputInfoDto = new ApiInputInfoDto(apiUpdateInfoArgs);
        AniApp curApp = oneApiInputInfoDto.getHostAppDao();
        checkApiUpdateElements(oneApiInputInfoDto, curApp, curUser);
        updateApiInfo(oneApiInputInfoDto, curApp);

        //update api-params info
        AniApi curApi = oneApiInputInfoDto.generateDao(curApp);
        updateApiParams(oneApiInputInfoDto, curApi);

    }
    public static void deleteApi(Map<String, String> oneApiDelInfo, AniUser curUser){

        MVCUtils.verifyRequiredElements(oneApiDelInfo, ApiInputInfoDto.requiredDeleteFieldKeys);
        AniApi curApi = AniApiService.getApiWithEntity(new ApiInputInfoDto(oneApiDelInfo)).get(0);
        if(curApi == null){
            throw new AniDataException("API_NOT_EXISTS");
        }
        AniAppService.checkAppOwner(curUser, curApi.hostApp);
        AniApi.deleteWithEntity(curApi);
    }
    private static AniApi updateApiInfo(ApiInputInfoDto oneApiUpdateInfo, AniApp curApp){
        AniApi oneApi = oneApiUpdateInfo.generateDao(curApp);
        try{
            oneApi.update();
        } catch (Exception e){
            throw new AniDataException("API_INFO_UPDATE_FAILED");
        }
        return oneApi;
    }
    private static void updateApiParams(ApiInputInfoDto apiInputInfoDto, AniApi hostApi){
        List<ApiParamDto> apiParams = ApiParamDto.generateFromJsonArrayStr(apiInputInfoDto.params, hostApi);
        checkApiParamsNotDuplicated(ApiParamDto.getParamsName(apiParams));
        List<List<ApiParamDto>> oldAndNewParams = splitNewParamsDto(apiParams);
        checkApiParamUpdateElements(oldAndNewParams.get(0), hostApi);
        saveUpdateApiParamsInfo(oldAndNewParams.get(0), hostApi);
        if(oldAndNewParams.get(2).size() > 0){
            saveApiParamsInfo(oldAndNewParams.get(2), hostApi);
        }
        deleteExcludedParams(apiParams, hostApi);
    }

    private static List<List<ApiParamDto>> splitNewParamsDto(List<ApiParamDto> apiParamsDto){
        List<List<ApiParamDto>> paramsOldAndNewDto = new ArrayList<List<ApiParamDto>>();
        for(int i = 0; i < 2; i++){
            paramsOldAndNewDto.add(
                    new ArrayList<ApiParamDto>()
            );
        }
        for(ApiParamDto oneApiParam: apiParamsDto){
            int oldOrNew;
            if(oneApiParam.id == null || oneApiParam.id < 1){
                oldOrNew = 1;//new
            }else{
                oldOrNew = 0;//old
            }
            paramsOldAndNewDto.get(oldOrNew).add(oneApiParam);
        }
        return paramsOldAndNewDto;
    }
    private static List<AniApiParam> saveUpdateApiParamsInfo(List<ApiParamDto> apiParamsDto, AniApi hostApi){
        List<AniApiParam> apiParams = ApiParamDto.getApiParamsDao(apiParamsDto, hostApi);
        try{
            Ebean.save(apiParams);
        } catch (Exception e){
            throw new AniDataException("API_PARAM_INFO_SAVING_FAILED");
        }
        return apiParams;
    }
    private static void checkApiParamUpdateElements(List<ApiParamDto> apiParams, AniApi oneApi){
        checkApiExistence(oneApi);
        checkApiParamsIdExistence(apiParams, oneApi);
        String[] requiredFields = null;
        for(ApiParamDto oneParamDto: apiParams){
            if(oneParamDto.id == null || oneParamDto.id < 1){
                requiredFields = ApiParamDto.requiredRegisterFieldKeys;
            }else{
                requiredFields = ApiParamDto.requiredUpdateFieldKeys;
            }
            MVCUtils.verifyRequiredElementsInObject(oneParamDto, requiredFields);
            checkApiParamElementsFormatLegality(oneParamDto);
        }
    }
    private static void deleteExcludedParams(List<ApiParamDto> allUpdateParams, AniApi oneApi){
        AniApiParam.deleteExcludedApiParamsWithName(ApiParamDto.getParamsName(allUpdateParams), oneApi);
    }
}
